`include "common.svh"
module backend #(
    parameter FRONTEND_WIDTH = 2,
    parameter COMMIT_WIDTH   = 2
) (
    input             clk,
    input             rst,
    //From frontend
    input             i_ibuf_valid,
    output            i_ibuf_ready,
    input             i_ibuf_entry_valid        [FRONTEND_WIDTH-1:0],
    input  IBUF_Entry i_ibuf_entry              [FRONTEND_WIDTH-1:0],
    //Redirect to frontend
    output            o_redirect_valid,
    output            o_redirect_replay,
    output word_t     o_redirect_pc,
    output            o_redirect_bpu_res_valid,
    output BPU_Res    o_redirect_bpu_res,
    //Memory Req Port
    output            o_mem_req_valid,
    output MEM_REQ    o_mem_req,
    input             o_mem_req_ready,
    output            o_mem_req_kill_prev,
    input             i_mem_early_wakeup_valid,
    input  PRF_IDX    i_mem_early_wakeup_prf_idx,
    //Memory Rsp Port
    input             i_mem_rsp_valid,
    input  MEM_RSP    i_mem_rsp,
    output            i_mem_rsp_ready
);
  logic   rob_redirect_valid;
  logic   rob_redirect_replay;
  word_t  rob_redirect_pc;
  logic   rob_redirect_bpu_res_valid;
  BPU_Res rob_redirect_bpu_res;
  //Decode Stage
  localparam DECODE_WIDTH = FRONTEND_WIDTH;
  logic   decode_redirect_valid;
  word_t  decode_redirect_pc;
  logic   decode_redirect_bpu_res_valid;
  BPU_Res decode_redirect_bpu_res;
  logic decode_o_valid, decode_o_ready;
  FrontendOP decode_o_fop[DECODE_WIDTH-1:0];
  logic decode_o_fop_valid[DECODE_WIDTH-1:0];
  decode #(DECODE_WIDTH) inst_decode (
      .flush(o_redirect_valid),
      .i_valid(i_ibuf_valid),
      .i_ready(i_ibuf_ready),
      .i_ibuf_entry_valid(i_ibuf_entry_valid),
      .i_ibuf_entry(i_ibuf_entry),
      .o_redirect_valid(decode_redirect_valid),
      .o_redirect_pc(decode_redirect_pc),
      .o_redirect_bpu_res_valid(decode_redirect_bpu_res_valid),
      .o_redirect_bpu_res(decode_redirect_bpu_res),
      .o_valid(decode_o_valid),
      .o_ready(decode_o_ready),
      .o_op(decode_o_fop),
      .o_op_valid(decode_o_fop_valid),
      .*
  );
  //Rename Stage
  localparam RENAME_WIDTH = DECODE_WIDTH;
  logic rename_i_commit_valid[COMMIT_WIDTH-1:0];
  COMMIT_TO_RENAME rename_i_commit_data[COMMIT_WIDTH-1:0];
  logic rename_i_commit_ready;

  logic busytable_clear_valid[RENAME_WIDTH-1:0];
  PRF_IDX busytable_clear_prf[RENAME_WIDTH-1:0];

  logic rename_o_valid;
  RenamedOP rename_o_rop[RENAME_WIDTH-1:0];
  logic rename_o_rop_valid[RENAME_WIDTH-1:0];
  logic rename_o_ready;
  rename #(RENAME_WIDTH, COMMIT_WIDTH, `GC_NUM) inst_rename (
      .busytable_clear_valid(busytable_clear_valid),
      .busytable_clear_prf(busytable_clear_prf),
      .i_valid(decode_o_valid & (~rob_redirect_valid)),
      .i_fop_valid(decode_o_fop_valid),
      .i_fop(decode_o_fop),
      .i_ready(decode_o_ready),
      .i_commit_valid(rename_i_commit_valid),
      .i_commit_data(rename_i_commit_data),
      .i_commit_ready(rename_i_commit_ready),
      .o_valid(rename_o_valid),
      .o_rop(rename_o_rop),
      .o_rop_valid(rename_o_rop_valid),
      .o_ready(rename_o_ready),
      .*
  );
  //Dispatch Stage
  localparam DISPATCH_WIDTH = RENAME_WIDTH;
  localparam RF_READ_WIDTH = 2 * DISPATCH_WIDTH;
  PRF_IDX dispatch_rf_raddr[RF_READ_WIDTH-1:0];
  word_t dispatch_rf_rdata[RF_READ_WIDTH-1:0];
  logic dispatch_rf_rdata_valid[RF_READ_WIDTH-1:0];
  logic dispatch_o_rob_write_valid;
  logic dispatch_o_rob_write_op_valid[DISPATCH_WIDTH-1:0];
  ROB_Entry dispatch_o_rob_write_op[DISPATCH_WIDTH-1:0];
  ROB_PTR dispatch_o_rob_write_rob_idx[DISPATCH_WIDTH-1:0];
  logic dispatch_o_rob_write_ready;
  logic dispatch_o_alu_valid[DISPATCH_WIDTH-1:0];
  ISSUE_OP dispatch_o_alu_iop[DISPATCH_WIDTH-1:0];
  logic dispatch_o_alu_ready;
  logic dispatch_o_bru_valid[DISPATCH_WIDTH-1:0];
  ISSUE_OP dispatch_o_bru_iop[DISPATCH_WIDTH-1:0];
  logic dispatch_o_bru_ready;
  logic dispatch_o_lsu_valid[DISPATCH_WIDTH-1:0];
  ISSUE_OP dispatch_o_lsu_iop[DISPATCH_WIDTH-1:0];
  logic dispatch_o_lsu_ready;
  logic dispatch_o_mdu_valid[DISPATCH_WIDTH-1:0];
  ISSUE_OP dispatch_o_mdu_iop[DISPATCH_WIDTH-1:0];
  logic dispatch_o_mdu_ready;
  logic dispatch_o_misc_valid[DISPATCH_WIDTH-1:0];
  ISSUE_OP dispatch_o_misc_iop[DISPATCH_WIDTH-1:0];
  logic dispatch_o_misc_ready;
  dispatch #(DISPATCH_WIDTH) inst_dispatch (
      .rst(rst | rob_redirect_valid),
      .i_valid(rename_o_valid),
      .i_rop(rename_o_rop),
      .i_rop_valid(rename_o_rop_valid),
      .i_ready(rename_o_ready),
      .rf_raddr(dispatch_rf_raddr),
      .rf_rdata(dispatch_rf_rdata),
      .rf_rdata_valid(dispatch_rf_rdata_valid),
      .o_rob_write_valid(dispatch_o_rob_write_valid),
      .o_rob_write_op_valid(dispatch_o_rob_write_op_valid),
      .o_rob_write_op(dispatch_o_rob_write_op),
      .o_rob_write_rob_idx(dispatch_o_rob_write_rob_idx),
      .o_rob_write_ready(dispatch_o_rob_write_ready),
      .o_alu_valid(dispatch_o_alu_valid),
      .o_alu_iop(dispatch_o_alu_iop),
      .o_alu_ready(dispatch_o_alu_ready),
      .o_bru_valid(dispatch_o_bru_valid),
      .o_bru_iop(dispatch_o_bru_iop),
      .o_bru_ready(dispatch_o_bru_ready),
      .o_lsu_valid(dispatch_o_lsu_valid),
      .o_lsu_iop(dispatch_o_lsu_iop),
      .o_lsu_ready(dispatch_o_lsu_ready),
      .o_mdu_valid(dispatch_o_mdu_valid),
      .o_mdu_iop(dispatch_o_mdu_iop),
      .o_mdu_ready(dispatch_o_mdu_ready),
      .o_misc_valid(dispatch_o_misc_valid),
      .o_misc_iop(dispatch_o_misc_iop),
      .o_misc_ready(dispatch_o_misc_ready),
      .*
  );

  //Issue Stage
  localparam RF_WRITE_WIDTH = `ALU_NUM + `BRU_NUM + `LSU_NUM + `MDU_NUM + `MISC_NUM;
  localparam WAKEUP_WIDTH = `ALU_NUM + `BRU_NUM + `LSU_NUM + `MDU_NUM;
  localparam ISSUE_WIDTH = `ALU_NUM + `BRU_NUM + `LSU_NUM + `MDU_NUM + `MISC_NUM;

  logic issue_i_write_valid[RF_WRITE_WIDTH-1:0];
  PRF_IDX issue_i_write_prf_idx[RF_WRITE_WIDTH-1:0];
  word_t issue_i_write_prf_data[RF_WRITE_WIDTH-1:0];
  logic issue_i_wakeup_valid[WAKEUP_WIDTH-1:0];
  PRF_IDX issue_i_wakeup_prf_idx[WAKEUP_WIDTH-1:0];

  logic execute_o_mdu_early_wakeup_valid[`MDU_NUM-1:0];
  PRF_IDX execute_o_mdu_early_wakeup_prf_idx[`MDU_NUM-1:0];

  logic issue_o_alu_valid[`ALU_NUM-1:0];
  ISSUE_OP issue_o_alu_iop[`ALU_NUM-1:0];
  logic issue_o_alu_ready;
  logic issue_o_bru_valid[`BRU_NUM-1:0];
  ISSUE_OP issue_o_bru_iop[`BRU_NUM-1:0];
  logic issue_o_bru_ready;
  logic issue_o_lsu_valid[`LSU_NUM-1:0];
  ISSUE_OP issue_o_lsu_iop[`LSU_NUM-1:0];
  logic issue_o_lsu_ready;
  logic issue_o_mdu_valid[`MDU_NUM-1:0];
  ISSUE_OP issue_o_mdu_iop[`MDU_NUM-1:0];
  logic issue_o_mdu_ready;
  logic issue_o_misc_valid[`MISC_NUM-1:0];
  ISSUE_OP issue_o_misc_iop[`MISC_NUM-1:0];
  logic issue_o_misc_ready;
  logic issue_o_rob_issue_valid[ISSUE_WIDTH-1:0];
  ROB_PTR issue_o_rob_issue_rob_idx[ISSUE_WIDTH-1:0];
  logic issue_o_rob_replay_valid[ISSUE_WIDTH-1:0];
  ROB_PTR issue_o_rob_replay_rob_idx[ISSUE_WIDTH-1:0];


  issue_wakeup #(`ALU_NUM, `BRU_NUM, `LSU_NUM, `MDU_NUM, WAKEUP_WIDTH) inst_issue_wakeup (
      .i_alu_valid(issue_o_alu_valid),
      .i_alu_iop(issue_o_alu_iop),
      .i_alu_ready(issue_o_alu_ready),
      .i_bru_valid(issue_o_bru_valid),
      .i_bru_iop(issue_o_bru_iop),
      .i_bru_ready(issue_o_bru_ready),
      .i_mdu_early_wakeup_valid(execute_o_mdu_early_wakeup_valid),
      .i_mdu_early_wakeup_prf_idx(execute_o_mdu_early_wakeup_prf_idx),
      .o_wakeup_valid(issue_i_wakeup_valid),
      .o_wakeup_prf_idx(issue_i_wakeup_prf_idx),
      .*
  );

  issue #(DISPATCH_WIDTH,RF_WRITE_WIDTH,WAKEUP_WIDTH,
  `ALU_NUM,`BRU_NUM,`LSU_NUM,`MDU_NUM,`MISC_NUM,
  `ALU_IQ_SIZE,`BRU_IQ_SIZE,`LSU_IQ_SIZE,`MDU_IQ_SIZE,
  `MISC_IQ_SIZE,ISSUE_WIDTH
  ) inst_issue (
      .rst(rst | rob_redirect_valid),
      .i_write_valid(issue_i_write_valid),
      .i_write_prf_idx(issue_i_write_prf_idx),
      .i_write_prf_data(issue_i_write_prf_data),
      .i_wakeup_valid(issue_i_wakeup_valid),
      .i_wakeup_prf_idx(issue_i_wakeup_prf_idx),
      .i_alu_valid(dispatch_o_alu_valid),
      .i_alu_iop(dispatch_o_alu_iop),
      .i_alu_ready(dispatch_o_alu_ready),
      .i_bru_valid(dispatch_o_bru_valid),
      .i_bru_iop(dispatch_o_bru_iop),
      .i_bru_ready(dispatch_o_bru_ready),
      .i_lsu_valid(dispatch_o_lsu_valid),
      .i_lsu_iop(dispatch_o_lsu_iop),
      .i_lsu_ready(dispatch_o_lsu_ready),
      .i_mdu_valid(dispatch_o_mdu_valid),
      .i_mdu_iop(dispatch_o_mdu_iop),
      .i_mdu_ready(dispatch_o_mdu_ready),
      .i_misc_valid(dispatch_o_misc_valid),
      .i_misc_iop(dispatch_o_misc_iop),
      .i_misc_ready(dispatch_o_misc_ready),
      .o_alu_valid(issue_o_alu_valid),
      .o_alu_iop(issue_o_alu_iop),
      .o_alu_ready(issue_o_alu_ready),
      .o_bru_valid(issue_o_bru_valid),
      .o_bru_iop(issue_o_bru_iop),
      .o_bru_ready(issue_o_bru_ready),
      .o_lsu_valid(issue_o_lsu_valid),
      .o_lsu_iop(issue_o_lsu_iop),
      .o_lsu_ready(issue_o_lsu_ready),
      .o_mdu_valid(issue_o_mdu_valid),
      .o_mdu_iop(issue_o_mdu_iop),
      .o_mdu_ready(issue_o_mdu_ready),
      .o_misc_valid(issue_o_misc_valid),
      .o_misc_iop(issue_o_misc_iop),
      .o_misc_ready(issue_o_misc_ready),
      .o_rob_replay_valid(issue_o_rob_replay_valid),
      .o_rob_replay_rob_idx(issue_o_rob_replay_rob_idx),
      .o_rob_issue_valid(issue_o_rob_issue_valid),
      .o_rob_issue_rob_idx(issue_o_rob_issue_rob_idx),
      .*
  );

  //Execute Stage
  CSR_ADDR  execute_csr_addr;
  logic     execute_csr_read;
  logic     execute_csr_write;
  logic     execute_csr_set;
  logic     execute_csr_clear;
  word_t    execute_csr_wdata;
  word_t    execute_csr_rdata;
  word_t    execute_csr_mepc;
  word_t    execute_csr_mtvec;

  logic     execute_o_write_valid             [RF_WRITE_WIDTH-1:0];
  PRF_IDX   execute_o_write_prf_idx           [RF_WRITE_WIDTH-1:0];
  word_t    execute_o_write_prf_data          [RF_WRITE_WIDTH-1:0];

  logic     execute_o_rob_finish_valid        [RF_WRITE_WIDTH-1:0];
  ROB_PTR   execute_o_rob_finish_rob_idx      [RF_WRITE_WIDTH-1:0];
  logic     execute_o_rob_exeception_valid    [RF_WRITE_WIDTH-1:0];
  ROB_PTR   execute_o_rob_exeception_rob_idx  [RF_WRITE_WIDTH-1:0];
  EXPT_CODE execute_o_rob_exeception_code     [RF_WRITE_WIDTH-1:0];
  logic     execute_o_rob_redirect_valid;
  ROB_PTR   execute_o_rob_redirect_rob_idx;
  word_t    execute_o_rob_redirect_pc;

  logic     execute_i_rob_order_valid;
  ROB_PTR   execute_i_rob_order_rob_idx;
  logic     execute_o_rob_mmio_valid          [      `LSU_NUM-1:0];
  ROB_PTR   execute_o_rob_mmio_rob_idx        [      `LSU_NUM-1:0];

  logic     execute_o_rob_bru_bpred_miss_valid[      `BRU_NUM-1:0];
  ROB_PTR   execute_o_rob_bru_rob_idx         [      `BRU_NUM-1:0];
  word_t    execute_o_rob_bru_dnpc            [      `BRU_NUM-1:0];
  BPU_Res   execute_o_rob_bru_correct_bpu_res [      `BRU_NUM-1:0];
  assign issue_i_write_valid = execute_o_write_valid;
  assign issue_i_write_prf_idx = execute_o_write_prf_idx;
  assign issue_i_write_prf_data = execute_o_write_prf_data;
  execute #(`STQ_SIZE,`ALU_NUM,`BRU_NUM,`LSU_NUM,`MDU_NUM,`MISC_NUM,RF_WRITE_WIDTH) inst_execute (
      .rst(rst | rob_redirect_valid),
      .i_alu_valid(issue_o_alu_valid),
      .i_alu_iop(issue_o_alu_iop),
      .i_alu_ready(issue_o_alu_ready),
      .i_bru_valid(issue_o_bru_valid),
      .i_bru_iop(issue_o_bru_iop),
      .i_bru_ready(issue_o_bru_ready),
      .i_lsu_valid(issue_o_lsu_valid),
      .i_lsu_iop(issue_o_lsu_iop),
      .i_lsu_ready(issue_o_lsu_ready),
      .i_mdu_valid(issue_o_mdu_valid),
      .i_mdu_iop(issue_o_mdu_iop),
      .i_mdu_ready(issue_o_mdu_ready),
      .i_misc_valid(issue_o_misc_valid),
      .i_misc_iop(issue_o_misc_iop),
      .i_misc_ready(issue_o_misc_ready),
      .csr_addr(execute_csr_addr),
      .csr_read(execute_csr_read),
      .csr_write(execute_csr_write),
      .csr_set(execute_csr_set),
      .csr_clear(execute_csr_clear),
      .csr_wdata(execute_csr_wdata),
      .csr_rdata(execute_csr_rdata),
      .csr_mepc(execute_csr_mepc),
      .csr_mtvec(execute_csr_mtvec),
      .o_mdu_early_wakeup_valid(execute_o_mdu_early_wakeup_valid),
      .o_mdu_early_wakeup_prf_idx(execute_o_mdu_early_wakeup_prf_idx),
      .o_write_valid(execute_o_write_valid),
      .o_write_prf_idx(execute_o_write_prf_idx),
      .o_write_prf_data(execute_o_write_prf_data),
      .o_rob_finish_valid(execute_o_rob_finish_valid),
      .o_rob_finish_rob_idx(execute_o_rob_finish_rob_idx),
      .o_rob_exeception_valid(execute_o_rob_exeception_valid),
      .o_rob_exeception_rob_idx(execute_o_rob_exeception_rob_idx),
      .o_rob_exeception_code(execute_o_rob_exeception_code),
      .o_rob_redirect_valid(execute_o_rob_redirect_valid),
      .o_rob_redirect_rob_idx(execute_o_rob_redirect_rob_idx),
      .o_rob_redirect_pc(execute_o_rob_redirect_pc),
      .i_rob_order_valid(execute_i_rob_order_valid),
      .i_rob_order_rob_idx(execute_i_rob_order_rob_idx),
      .o_rob_mmio_valid(execute_o_rob_mmio_valid),
      .o_rob_mmio_rob_idx(execute_o_rob_mmio_rob_idx),
      .o_rob_bru_bpred_miss_valid(execute_o_rob_bru_bpred_miss_valid),
      .o_rob_bru_rob_idx(execute_o_rob_bru_rob_idx),
      .o_rob_bru_dnpc(execute_o_rob_bru_dnpc),
      .o_rob_bru_correct_bpu_res(execute_o_rob_bru_correct_bpu_res),
      .*
  );
  logic commit_i_valid;
  logic commit_i_op_valid[COMMIT_WIDTH-1:0];
  ROB_Entry commit_i_op[COMMIT_WIDTH-1:0];
  ROB_State commit_i_op_state[COMMIT_WIDTH-1:0];
  logic commit_i_restore_gc[COMMIT_WIDTH-1:0];
  logic commit_i_ready;
  logic csr_commit_valid[COMMIT_WIDTH-1:0];
  commit #(COMMIT_WIDTH) inst_commit (
      .i_valid(commit_i_valid),
      .i_op_valid(commit_i_op_valid),
      .i_op(commit_i_op),
      .i_op_state(commit_i_op_state),
      .i_restore_gc(commit_i_restore_gc),
      .i_ready(commit_i_ready),
      .o_valid(rename_i_commit_valid),
      .o_data(rename_i_commit_data),
      .o_ready(rename_i_commit_ready),
      .csr_commit_valid(csr_commit_valid),
      .*
  );
  //CSR
  csr #(COMMIT_WIDTH) inst_csr (
      .csr_addr(execute_csr_addr),
      .csr_read(execute_csr_read),
      .csr_write(execute_csr_write),
      .csr_set(execute_csr_set),
      .csr_clear(execute_csr_clear),
      .csr_wdata(execute_csr_wdata),
      .csr_rdata(execute_csr_rdata),
      .mepc(execute_csr_mepc),
      .mtvec(execute_csr_mtvec),
      .commit_valid(csr_commit_valid),
      .*
  );
  //Regfile
  regfile_wrapper #(RF_READ_WIDTH, RF_WRITE_WIDTH) inst_regfile (
      .raddr (dispatch_rf_raddr),
      .rdata (dispatch_rf_rdata),
      .wvalid(execute_o_write_valid),
      .waddr (execute_o_write_prf_idx),
      .wdata (execute_o_write_prf_data),
      .*
  );
  //Busy table
  busytable #(RF_READ_WIDTH, RENAME_WIDTH, RF_WRITE_WIDTH) inst_busytable (
      .rst(rst | rob_redirect_valid),
      .read_prf(dispatch_rf_raddr),
      .read_prf_valid(dispatch_rf_rdata_valid),
      .clear_valid(busytable_clear_valid),
      .clear_prf(busytable_clear_prf),
      .rf_write_valid(execute_o_write_valid),
      .rf_write_prf(execute_o_write_prf_idx),
      .*
  );
  //ROB
  rob #(DISPATCH_WIDTH, ISSUE_WIDTH, COMMIT_WIDTH, `BRU_NUM, `LSU_NUM) inst_rob (
      .i_write_valid(dispatch_o_rob_write_valid),
      .i_write_op_valid(dispatch_o_rob_write_op_valid),
      .i_write_op(dispatch_o_rob_write_op),
      .i_write_rob_idx(dispatch_o_rob_write_rob_idx),
      .i_write_ready(dispatch_o_rob_write_ready),
      .i_issue_valid(issue_o_rob_issue_valid),
      .i_issue_rob_idx(issue_o_rob_issue_rob_idx),
      .i_finish_valid(execute_o_rob_finish_valid),
      .i_finish_rob_idx(execute_o_rob_finish_rob_idx),
      .i_exeception_valid(execute_o_rob_exeception_valid),
      .i_exeception_rob_idx(execute_o_rob_exeception_rob_idx),
      .i_exeception_code(execute_o_rob_exeception_code),
      .i_bru_bpred_miss_valid(execute_o_rob_bru_bpred_miss_valid),
      .i_bru_rob_idx(execute_o_rob_bru_rob_idx),
      .i_bru_dnpc(execute_o_rob_bru_dnpc),
      .i_bru_correct_bpu_res(execute_o_rob_bru_correct_bpu_res),
      .i_misc_redirect_valid(execute_o_rob_redirect_valid),
      .i_misc_redirect_rob_idx(execute_o_rob_redirect_rob_idx),
      .i_misc_redirect_pc(execute_o_rob_redirect_pc),
      .i_replay_valid(issue_o_rob_replay_valid),
      .i_replay_rob_idx(issue_o_rob_replay_rob_idx),
      .o_order_valid(execute_i_rob_order_valid),
      .o_order_rob_idx(execute_i_rob_order_rob_idx),
      .i_mmio_valid(execute_o_rob_mmio_valid),
      .i_mmio_rob_idx(execute_o_rob_mmio_rob_idx),
      .o_commit_valid(commit_i_valid),
      .o_commit_op_valid(commit_i_op_valid),
      .o_commit_op(commit_i_op),
      .o_commit_op_state(commit_i_op_state),
      .o_commit_restore_gc(commit_i_restore_gc),
      .o_commit_ready(commit_i_ready),
      .o_redirect_valid(rob_redirect_valid),
      .o_redirect_replay(rob_redirect_replay),
      .o_redirect_pc(rob_redirect_pc),
      .o_redirect_bpu_res_valid(rob_redirect_bpu_res_valid),
      .o_redirect_bpu_res(rob_redirect_bpu_res),
      .*
  );

  assign o_redirect_valid  = rob_redirect_valid | decode_redirect_valid;
  assign o_redirect_replay = rob_redirect_replay;
  MUX_PRIO #(2, `WORD_BITS) mux_o_redirect_pc (
      .sel ({decode_redirect_valid, rob_redirect_valid}),
      .din ({decode_redirect_pc, rob_redirect_pc}),
      .dout(o_redirect_pc)
  );

  MUX_PRIO #(2, 1) mux_o_redirect_bpu_res_valid (
      .sel ({decode_redirect_valid, rob_redirect_valid}),
      .din ({decode_redirect_bpu_res_valid, rob_redirect_bpu_res_valid}),
      .dout(o_redirect_bpu_res_valid)
  );

  localparam BPU_RES_SIZE = $size(BPU_Res);
  MUX_PRIO #(2, BPU_RES_SIZE) mux_o_redirect_bpu_res (
      .sel ({decode_redirect_valid, rob_redirect_valid}),
      .din ({decode_redirect_bpu_res, rob_redirect_bpu_res}),
      .dout(o_redirect_bpu_res)
  );

  `PERF_EVENT(rename_bubble_cycle, ~(decode_o_valid & decode_o_fop_valid[0]) & decode_o_ready);
  `PERF_EVENT(commit_bubble_cycle,
              ~(commit_i_valid & commit_i_ready & (commit_i_op_valid[0] | commit_i_op_valid[1])));
  `PERF_EVENT(commit_one_op,
              (commit_i_valid & commit_i_ready & commit_i_op_valid[0] & ~commit_i_op_valid[1]));
  `PERF_EVENT(commit_two_op,
              (commit_i_valid & commit_i_ready & commit_i_op_valid[0] & commit_i_op_valid[1]));

  `PERF_EVENT(rename_busy, ~decode_o_ready);
  `PERF_EVENT(dispatch_busy, ~rename_o_ready);
  `PERF_EVENT(rob_full, ~dispatch_o_rob_write_ready);
  `PERF_EVENT(issue_alu_full, ~dispatch_o_alu_ready);
  `PERF_EVENT(issue_bru_full, ~dispatch_o_bru_ready);
  `PERF_EVENT(issue_lsu_full, ~dispatch_o_lsu_ready);
  `PERF_EVENT(issue_mdu_full, ~dispatch_o_mdu_ready);
  `PERF_EVENT(issue_misc_full, ~dispatch_o_misc_ready);

endmodule
